仅含2个唯一点的高维数据t-SNE降维后2D投影分散原因
问题根因
t-SNE输出散点没有聚成2个点,和绘图逻辑无关,是算法特性+默认参数完全不适配你的极端数据集导致的:
- t-SNE本身不会强制高维完全相同的点映射到低维的同一个坐标。它的核心逻辑是把高维点对的相似度转化为低维的概率分布,优化过程用梯度下降迭代,哪怕两个点高维完全重合,计算得到的相似度也不是绝对的1,迭代过程中自然会产生偏移,不会完全叠在一起。
- 默认参数的
perplexity(困惑度)是造成点严重分散的核心原因。scikit-learn中TSNE的默认困惑度值为30,这个参数的作用是定义每个点计算相似度时参考的近邻数量,要求每个点周围至少有数十个有效近邻才能得到稳定的相似度分布。但你的数据集总共只有2个唯一值,有效独立样本量远小于默认困惑度要求的近邻规模,这时候算法的相似度计算完全失真,会强行把同组的重复点拆成零散分布,来满足概率分布的约束条件。 - 本质上你当前的数据集完全不适合用t-SNE做降维:总共只有2个离散的12维点,不存在t-SNE擅长捕捉的局部流形结构,属于典型的工具场景错配。
可落地的解决方法
- 最优方案:先对数据去重后再做t-SNE计算,避免重复值干扰参数估计,最后再把映射结果匹配回原始样本即可。参考调整后的代码:
import numpy as np from sklearn.manifold import TSNE def create_subplot(z_tensor, index: int, title: str, axes): z_np = z_tensor.detach().cpu().numpy() # 提取唯一值,同时记录每个原始样本对应的唯一值ID unique_pts, sample_labels = np.unique(z_np, axis=0, return_inverse=True) # 唯一值仅2个,困惑度设为最小值1即可,匹配极小样本量的计算需求 tsne = TSNE(n_components=2, random_state=123, perplexity=1) embedded_unique = tsne.fit_transform(unique_pts) # 把降维结果匹配回全部512个原始样本 embedded_all = embedded_unique[sample_labels] # 绘图时可按类别传c参数上色,区分两个簇 axes[index].scatter(x=embedded_all[:, 0], y=embedded_all[:, 1], c=sample_labels) axes[index].set_title(title)
- 如果坚持要把全部512个点直接传入TSNE计算,需要把
perplexity调到5以下,同时适当调低learning_rate参数减小迭代步长,避免点被甩得过散。但即使调整参数,相同高维点的低维映射也只会聚成两个紧凑的簇,不会完全重合为两个点。 - 对于仅2类取值的简单数据集,不需要用t-SNE做降维,直接给两类样本分配两个固定的二维坐标绘图即可,结果更准确可解释。
内容的提问来源于stack exchange,提问作者Gooby
相关产品推荐
相关产品推荐

