import numpy as np import matplotlib.pyplot as plt from sklearn.decomposition import PCA import os import glob # ================= 配置区域 ================= data_root = "/root/Coding/RoboGauge/logs_latent" # 地形列表 (我们需要遍历所有地形来收集同一个指令的数据) terrains = ['flat', 'wave', 'slope_fd', 'slope_bd', 'stairs_fd', 'stairs_bd', 'obstacle'] # 指令 ID 与含义的映射 (根据你的描述) command_map = { 0: "Pos X", 1: "Neg X", 2: "Pos Y", 3: "Neg Y", 4: "Pos Yaw", 5: "Neg Yaw" } # 颜色映射 (为6种指令分配不同颜色) cmd_colors = { 0: '#d62728', # 红 1: '#1f77b4', # 蓝 2: '#2ca02c', # 绿 3: '#ff7f0e', # 橙 4: '#9467bd', # 紫 5: '#8c564b' # 棕 } # 每种指令最大保留样本数 # 因为我们要把7个地形的数据合起来,数据量会很大,必须采样 # 建议 1000 - 2000,太少看不出分布,太多会糊成一团 MAX_SAMPLES_PER_CMD = 3000 # ================= 功能函数 ================= def load_combined_command_data(root_path, terrain_list, cmd_id): """ 遍历所有地形文件夹,寻找指定 cmd_id 的 npz 文件,并将它们全部合并 """ cmd_latents = [] filename = f"moe_info_{cmd_id}.npz" for t_name in terrain_list: # 搜索路径: /root/.../go2_moe_{terrain}_latent/*/moe_info_{id}.npz search_pattern = os.path.join(root_path, f"go2_moe_{t_name}_latent", "*", filename) files = glob.glob(search_pattern) for f in files: try: data = np.load(f) if 'latent' in data: cmd_latents.append(data['latent']) except: pass if not cmd_latents: return None # 合并该指令下所有地形的数据 combined = np.concatenate(cmd_latents, axis=0) return combined # ================= 主程序 ================= print(f"Start processing. Grouping by COMMAND (0-5)...") # 1. 数据收集与预处理 all_data = [] # 存放 latent 向量 all_labels = [] # 存放对应的指令 ID (0, 1, 2...) for cmd_id, cmd_name in command_map.items(): print(f" - Loading data for Command {cmd_id}: {cmd_name} ...", end=" ") # 获取该指令在所有地形下的数据汇总 raw_data = load_combined_command_data(data_root, terrains, cmd_id) if raw_data is not None: # 随机下采样 (防止数据量过大) n_total = len(raw_data) if n_total > MAX_SAMPLES_PER_CMD: indices = np.random.choice(n_total, MAX_SAMPLES_PER_CMD, replace=False) data_sample = raw_data[indices] else: data_sample = raw_data all_data.append(data_sample) # 记录标签:有多少个数据,就存多少个 label all_labels.extend([cmd_id] * len(data_sample)) print(f"Got {len(data_sample)} samples (from {n_total})") else: print("No data found!") if not all_data: print("Error: No data loaded.") exit() # 将列表转换为大矩阵 X = np.concatenate(all_data, axis=0) y = np.array(all_labels) # 2. PCA 降维 print(f"Running PCA on total {X.shape[0]} samples...") pca = PCA(n_components=2) X_2d = pca.fit_transform(X) # 3. 可视化绘制 plt.figure(figsize=(10, 8), dpi=120) # 遍历 0-5 进行绘制 for cmd_id in command_map.keys(): # 提取属于当前指令的 2D 点 indices = (y == cmd_id) points = X_2d[indices] if len(points) > 0: plt.scatter( points[:, 0], points[:, 1], c=cmd_colors[cmd_id], label=command_map[cmd_id], alpha=0.6, # 透明度 s=15 # 点大小 ) plt.title("PCA of Latent Space grouped by Control Command (All Terrains Mixed)") plt.xlabel("PC 1") plt.ylabel("PC 2") plt.legend(title="Control Commands", markerscale=1.5) plt.grid(True, linestyle='--', alpha=0.4) save_path = 'latent_pca_by_command_mixed.png' plt.savefig(save_path) print(f"Done! Visualization saved to {save_path}") plt.show()