v1.0.2-rc2; fix robogauge eval return None bug
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
# 20260325
|
||||||
|
## v1.0.2-rc2
|
||||||
|
1. 修复robogauge评估中返回None导致的训练中断问题
|
||||||
# 20260126
|
# 20260126
|
||||||
## v1.0.2-rc1
|
## v1.0.2-rc1
|
||||||
1. 修改高速移动的训练文件到最终版,删除配置中无用注释
|
1. 修改高速移动的训练文件到最终版,删除配置中无用注释
|
||||||
|
|||||||
@@ -253,6 +253,7 @@ class OnPolicyRunner:
|
|||||||
if self.robogauge_client is None:
|
if self.robogauge_client is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
if it % 500 == 0 or last_model:
|
if it % 500 == 0 or last_model:
|
||||||
# export jit model
|
# export jit model
|
||||||
jit_dir = os.path.join(self.log_dir, 'jit_models')
|
jit_dir = os.path.join(self.log_dir, 'jit_models')
|
||||||
@@ -266,25 +267,42 @@ class OnPolicyRunner:
|
|||||||
task_name=task_name,
|
task_name=task_name,
|
||||||
experiment_name=self.cfg["experiment_name"]
|
experiment_name=self.cfg["experiment_name"]
|
||||||
)
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[WARN] RoboGauge submit failed at step {it}: {e}")
|
||||||
|
return
|
||||||
check_times = 1
|
check_times = 1
|
||||||
if last_model:
|
if last_model:
|
||||||
check_times = int(1e9) # keep checking until the last model is evaluated
|
check_times = int(1e9) # keep checking until the last model is evaluated
|
||||||
while check_times > 0:
|
while check_times > 0:
|
||||||
check_times -= 1
|
check_times -= 1
|
||||||
|
try:
|
||||||
self.robogauge_client.monitor_tasks()
|
self.robogauge_client.monitor_tasks()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[WARN] RoboGauge monitor failed at step {it}: {e}")
|
||||||
|
break
|
||||||
results_dir = os.path.join(self.log_dir, 'robogauge_results')
|
results_dir = os.path.join(self.log_dir, 'robogauge_results')
|
||||||
os.makedirs(results_dir, exist_ok=True)
|
os.makedirs(results_dir, exist_ok=True)
|
||||||
result_received = False
|
result_received = False
|
||||||
for task_id, resp in self.robogauge_client.response_data.items():
|
for task_id, resp in self.robogauge_client.response_data.items():
|
||||||
scores = resp['results']['scores']
|
if not isinstance(resp, dict):
|
||||||
step = resp['step']
|
print(f"[WARN] RoboGauge returned an invalid response for task {task_id}: {resp}")
|
||||||
|
continue
|
||||||
|
results = resp.get('results')
|
||||||
|
step = resp.get('step', it)
|
||||||
|
if results is None:
|
||||||
|
print(f"[WARN] RoboGauge returned empty results for task {task_id} at step {step}.")
|
||||||
|
continue
|
||||||
|
scores = results.get('scores')
|
||||||
|
if scores is None:
|
||||||
|
print(f"[WARN] RoboGauge results for task {task_id} at step {step} do not contain 'scores'.")
|
||||||
|
continue
|
||||||
if step == it:
|
if step == it:
|
||||||
result_received = True
|
result_received = True
|
||||||
for key, val in scores.items():
|
for key, val in scores.items():
|
||||||
self.writer.add_scalar(f'RoboGauge/{key}', val, step)
|
self.writer.add_scalar(f'RoboGauge/{key}', val, step)
|
||||||
results_path = os.path.join(results_dir, f'results_{step}.yaml')
|
results_path = os.path.join(results_dir, f'results_{step}.yaml')
|
||||||
with open(results_path, 'w', encoding='utf-8') as f:
|
with open(results_path, 'w', encoding='utf-8') as f:
|
||||||
yaml.dump(resp['results'], f, allow_unicode=True, sort_keys=False)
|
yaml.dump(results, f, allow_unicode=True, sort_keys=False)
|
||||||
|
|
||||||
if last_model and result_received:
|
if last_model and result_received:
|
||||||
print(f"RoboGauge result for step {it} received. Exiting wait loop.")
|
print(f"RoboGauge result for step {it} received. Exiting wait loop.")
|
||||||
|
|||||||
@@ -298,6 +298,7 @@ class OnPolicyRunnerCTS:
|
|||||||
if self.robogauge_client is None:
|
if self.robogauge_client is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
if it % 500 == 0 or last_model:
|
if it % 500 == 0 or last_model:
|
||||||
# export jit model
|
# export jit model
|
||||||
jit_dir = os.path.join(self.log_dir, 'jit_models')
|
jit_dir = os.path.join(self.log_dir, 'jit_models')
|
||||||
@@ -311,25 +312,42 @@ class OnPolicyRunnerCTS:
|
|||||||
task_name=task_name,
|
task_name=task_name,
|
||||||
experiment_name=self.cfg["experiment_name"]
|
experiment_name=self.cfg["experiment_name"]
|
||||||
)
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[WARN] RoboGauge submit failed at step {it}: {e}")
|
||||||
|
return
|
||||||
check_times = 1
|
check_times = 1
|
||||||
if last_model:
|
if last_model:
|
||||||
check_times = int(1e9) # keep checking until manually stopped
|
check_times = int(1e9) # keep checking until manually stopped
|
||||||
while check_times > 0:
|
while check_times > 0:
|
||||||
check_times -= 1
|
check_times -= 1
|
||||||
|
try:
|
||||||
self.robogauge_client.monitor_tasks()
|
self.robogauge_client.monitor_tasks()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[WARN] RoboGauge monitor failed at step {it}: {e}")
|
||||||
|
break
|
||||||
results_dir = os.path.join(self.log_dir, 'robogauge_results')
|
results_dir = os.path.join(self.log_dir, 'robogauge_results')
|
||||||
os.makedirs(results_dir, exist_ok=True)
|
os.makedirs(results_dir, exist_ok=True)
|
||||||
result_received = False
|
result_received = False
|
||||||
for task_id, resp in self.robogauge_client.response_data.items():
|
for task_id, resp in self.robogauge_client.response_data.items():
|
||||||
scores = resp['results']['scores']
|
if not isinstance(resp, dict):
|
||||||
step = resp['step']
|
print(f"[WARN] RoboGauge returned an invalid response for task {task_id}: {resp}")
|
||||||
|
continue
|
||||||
|
results = resp.get('results')
|
||||||
|
step = resp.get('step', it)
|
||||||
|
if results is None:
|
||||||
|
print(f"[WARN] RoboGauge returned empty results for task {task_id} at step {step}.")
|
||||||
|
continue
|
||||||
|
scores = results.get('scores')
|
||||||
|
if scores is None:
|
||||||
|
print(f"[WARN] RoboGauge results for task {task_id} at step {step} do not contain 'scores'.")
|
||||||
|
continue
|
||||||
if step == it:
|
if step == it:
|
||||||
result_received = True
|
result_received = True
|
||||||
for key, val in scores.items():
|
for key, val in scores.items():
|
||||||
self.writer.add_scalar(f'RoboGauge/{key}', val, step)
|
self.writer.add_scalar(f'RoboGauge/{key}', val, step)
|
||||||
results_path = os.path.join(results_dir, f'results_{step}.yaml')
|
results_path = os.path.join(results_dir, f'results_{step}.yaml')
|
||||||
with open(results_path, 'w', encoding='utf-8') as f:
|
with open(results_path, 'w', encoding='utf-8') as f:
|
||||||
yaml.dump(resp['results'], f, allow_unicode=True, sort_keys=False)
|
yaml.dump(results, f, allow_unicode=True, sort_keys=False)
|
||||||
|
|
||||||
if last_model and result_received:
|
if last_model and result_received:
|
||||||
print(f"RoboGauge result for step {it} received. Exiting wait loop.")
|
print(f"RoboGauge result for step {it} received. Exiting wait loop.")
|
||||||
|
|||||||
@@ -36,7 +36,39 @@ def fast_read(event_file_path, tag_names):
|
|||||||
if value.tag in tag_names:
|
if value.tag in tag_names:
|
||||||
tag_data[event.step][value.tag] = value.simple_value
|
tag_data[event.step][value.tag] = value.simple_value
|
||||||
|
|
||||||
return pd.DataFrame(tag_data).T
|
df = pd.DataFrame(tag_data).T
|
||||||
|
df.index.name = 'step'
|
||||||
|
return df
|
||||||
|
|
||||||
|
def normalize_tb_df(tb_df):
|
||||||
|
tb_df = tb_df.copy()
|
||||||
|
|
||||||
|
if 'step' not in tb_df.columns:
|
||||||
|
first_col = tb_df.columns[0] if len(tb_df.columns) > 0 else None
|
||||||
|
if first_col is not None and str(first_col).startswith('Unnamed:'):
|
||||||
|
tb_df = tb_df.rename(columns={first_col: 'step'})
|
||||||
|
elif tb_df.index.name == 'step':
|
||||||
|
tb_df = tb_df.reset_index()
|
||||||
|
else:
|
||||||
|
tb_df = tb_df.reset_index().rename(columns={'index': 'step'})
|
||||||
|
|
||||||
|
tb_df['step'] = pd.to_numeric(tb_df['step'], errors='coerce')
|
||||||
|
tb_df = tb_df.dropna(subset=['step'])
|
||||||
|
tb_df['step'] = tb_df['step'].astype(int)
|
||||||
|
return tb_df
|
||||||
|
|
||||||
|
def get_tb_value(tb_df, step, candidate_tags):
|
||||||
|
row = tb_df[tb_df['step'] == step]
|
||||||
|
if row.empty:
|
||||||
|
raise KeyError(f"No tensorboard entry found for step={step}.")
|
||||||
|
|
||||||
|
for tag in candidate_tags:
|
||||||
|
if tag not in row.columns:
|
||||||
|
continue
|
||||||
|
values = row[tag].dropna().values
|
||||||
|
if len(values) > 0:
|
||||||
|
return float(values[0])
|
||||||
|
raise KeyError(f"No tensorboard value found for step={step} in tags: {candidate_tags}")
|
||||||
|
|
||||||
class Collector:
|
class Collector:
|
||||||
def __init__(self, log_dirs):
|
def __init__(self, log_dirs):
|
||||||
@@ -58,14 +90,14 @@ class Collector:
|
|||||||
self.output_tb = self.output_dir / "tb.csv"
|
self.output_tb = self.output_dir / "tb.csv"
|
||||||
if self.output_tb.exists():
|
if self.output_tb.exists():
|
||||||
print(f"Loading existing tensorboard data from {self.output_tb}")
|
print(f"Loading existing tensorboard data from {self.output_tb}")
|
||||||
self.tb_df = pd.read_csv(self.output_tb)
|
self.tb_df = normalize_tb_df(pd.read_csv(self.output_tb))
|
||||||
else:
|
else:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
print(f"Start reading tensorboard events at {time.ctime(start_time)}")
|
print(f"Start reading tensorboard events at {time.ctime(start_time)}")
|
||||||
self.tb_df = fast_read(str(self.log_dirs.glob("events.out.tfevents.*").__next__()), [
|
self.tb_df = normalize_tb_df(fast_read(str(self.log_dirs.glob("events.out.tfevents.*").__next__()), [
|
||||||
'Terrain/terrain_level_all', 'Episode/terrain_level_all',
|
'Terrain/terrain_level_all', 'Episode/terrain_level_all',
|
||||||
'RoboGauge/benchmark'
|
'RoboGauge/benchmark'
|
||||||
])
|
]))
|
||||||
print(f"Finished reading tensorboard events in {time.time() - start_time:.2f} seconds.")
|
print(f"Finished reading tensorboard events in {time.time() - start_time:.2f} seconds.")
|
||||||
self.tb_df.to_csv(self.output_tb, index=False)
|
self.tb_df.to_csv(self.output_tb, index=False)
|
||||||
print(f"Saved tensorboard data to {self.output_tb}")
|
print(f"Saved tensorboard data to {self.output_tb}")
|
||||||
@@ -109,7 +141,11 @@ class Collector:
|
|||||||
self.datas[f'{terrain_name}_mean@25'].append(float(data['robust_score'][terrain_name]['mean@25']))
|
self.datas[f'{terrain_name}_mean@25'].append(float(data['robust_score'][terrain_name]['mean@25']))
|
||||||
self.datas[f'{terrain_name}_mean@50'].append(float(data['robust_score'][terrain_name]['mean@50']))
|
self.datas[f'{terrain_name}_mean@50'].append(float(data['robust_score'][terrain_name]['mean@50']))
|
||||||
|
|
||||||
self.datas['terrain_level'].append(float(self.tb_df[self.tb_df['step'] == it]['value'].values[0]))
|
self.datas['terrain_level'].append(get_tb_value(
|
||||||
|
self.tb_df,
|
||||||
|
it,
|
||||||
|
['Terrain/terrain_level_all', 'Episode/terrain_level_all']
|
||||||
|
))
|
||||||
df = pd.DataFrame(self.datas)
|
df = pd.DataFrame(self.datas)
|
||||||
df.to_csv(self.output_csv, index=False)
|
df.to_csv(self.output_csv, index=False)
|
||||||
print(f"Saved merged results to {self.output_csv}")
|
print(f"Saved merged results to {self.output_csv}")
|
||||||
@@ -117,6 +153,8 @@ class Collector:
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("--log-dirs")
|
parser.add_argument("--log-dirs")
|
||||||
|
parser.add_argument("--read-robogauge", default=True, type=lambda x: (str(x).lower() in ['true', '1']), help="Whether to read robogauge_results")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
collector = Collector(args.log_dirs)
|
collector = Collector(args.log_dirs)
|
||||||
# collector.collect()
|
if args.read_robogauge:
|
||||||
|
collector.collect()
|
||||||
|
|||||||
Reference in New Issue
Block a user