Skip to content

地形分类可视化 #28

@LRuYuan

Description

@LRuYuan

打扰一下,我想要知道训练后,这个地形分类分出的情况,就用论文中提到的t-SNE可视化encoder网络对于地形的编码结果,发现编码的结果仅仅只有一种地形,下面是我的用于可视化的代码,temperature默认是3,我调整这个参数,便可以分出不同的地形,但是默认是3,请问是不是这个temperature=3的时候这个对地形的编码根本没有实现?还是说我的这个可视化的代码逻辑有问题?
def update(self, obs_history, next_critic_obs, lr=None):
# 用于降采样

    if lr is not None:
        self.learning_rate = lr
        for param_group in self.optimizer.param_groups:
            param_group['lr'] = self.learning_rate
            
    vel = next_critic_obs[:, self.num_one_step_obs:self.num_one_step_obs+3].detach()
    next_obs = next_critic_obs.detach()[:, 3:self.num_one_step_obs+3]

    z_s = self.encoder(obs_history)
    z_t = self.target(next_obs)
    pred_vel, z_s = z_s[..., :3], z_s[..., 3:]

    # print("obs_history shape:", obs_history.shape)
    # print("next_obs shape:", next_obs.shape)

    z_s = F.normalize(z_s, dim=-1, p=2)
    z_t = F.normalize(z_t, dim=-1, p=2)

    with torch.no_grad():
        w = self.proto.weight.data.clone()
        w = F.normalize(w, dim=-1, p=2)
        self.proto.weight.copy_(w)

    score_s = z_s @ self.proto.weight.T
    score_t = z_t @ self.proto.weight.T

    # print("score_s shape",score_s.shape)

    with torch.no_grad():
        q_s = sinkhorn(score_s)
        q_t = sinkhorn(score_t)
    # print("q_s shape",q_s.shape)

    log_p_s = F.log_softmax(score_s / self.temperature, dim=-1)
    log_p_t = F.log_softmax(score_t / self.temperature, dim=-1)
    print(f"temperature:{self.temperature}")
    
    if self.epoch % 8000 == 0:
        # 1. 提取【全量】10.4万个数据点
        # 这一步是为了让所有的点都参与构建隐式结构(邻域图)
        full_data = z_s.detach().cpu().numpy()
        full_labels = torch.argmax(q_s, dim=1).detach().cpu().numpy()

        # 2. 使用 openTSNE 对全量数据进行快速降维
        # 它底层使用 k-NN 树,速度极快,10万数据通常只需不到 1 分钟
        tsne = FastTSNE(
            n_components=2,
            perplexity=30,
            n_jobs=-1,  # 使用所有 CPU 核心并行计算
            random_state=42
        )
        # full_feature_2d 包含了全部 10.4 万个点的二维坐标
        full_feature_2d = tsne.fit(full_data)

        # 3. 子集采样(对应论文中的“只显示数据子集”)
        # 坐标已经受到 10.4 万点整体流形的影响,此时我们随机抽取 1 万个点用来画图
        n_landmarks = 5000
        indices = np.random.permutation(full_data.shape[0])[:n_landmarks]
        
        sampled_feature_2d = full_feature_2d[indices]
        sampled_labels = full_labels[indices]

        # 4. 绘图(画点太多容易变成一坨黑,所以调小点的大小 s=5)
        plt.figure(figsize=(20, 16))
        plt.scatter(sampled_feature_2d[:, 0], sampled_feature_2d[:, 1], 
                    c=sampled_labels, cmap='viridis', s=5, alpha=0.8)
        plt.title(f"Terrain Classification at Epoch {self.epoch} (10k sampled from 104k)")

        plt.savefig(f"picture/epoch_{self.epoch}.png")
        plt.close()
        
    self.epoch +=1


    swap_loss = -0.5 * (q_s * log_p_t + q_t * log_p_s).mean()

    estimation_loss = F.mse_loss(pred_vel, vel)

    losses = estimation_loss + swap_loss

    self.optimizer.zero_grad()
    losses.backward()
    nn.utils.clip_grad_norm_(self.parameters(), self.max_grad_norm)
    self.optimizer.step()

    return estimation_loss.item(), swap_loss.item()
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions