Python中sklearn的TSNE降维后向量与原向量对应关系问题

现在手里有 360w 个 200 维向量,存放在 np.array 里,想把这些向量降维到二维然后投影出来,观察聚类情况。 使用 TSNE 的时候,出现问题,会卡住,过一段时间自动 kill 掉,但是如果用低维小数据测试则可以正常运行。

请问是不是数据太大,是否应该在训练时就调低向量维度?或者除 TSNE 外其他适合实现该数据降维的轮子。 环境为 python3.5,osx


Python中sklearn的TSNE降维后向量与原向量对应关系问题
16 回复

想要没有性能问题和内存问题,请不要用 sklearn,效率极差。
手写一个就好


TSNE降维后向量与原向量的对应关系是通过索引顺序保持的。简单来说,TSNE.fit_transform(X)返回的二维/三维数组的第i行,就对应输入数据X的第i行。

举个例子,假设你有一个形状为(100, 50)的原始数据矩阵X,表示100个样本,每个样本有50个特征。执行TSNE降维到2维:

from sklearn.manifold import TSNE
import numpy as np

# 假设这是你的原始数据,100个样本,50维特征
X = np.random.randn(100, 50)

# 创建TSNE模型,降维到2维
tsne = TSNE(n_components=2, random_state=42, perplexity=30)

# 执行降维,得到新坐标
X_tsne = tsne.fit_transform(X)

print(f"原始数据形状: {X.shape}")  # (100, 50)
print(f"降维后形状: {X_tsne.shape}")  # (100, 2)

# 验证对应关系:第i个样本的对应关系
i = 42  # 随便选一个索引
print(f"\n原始数据第{i}个样本 (前5个特征): {X[i, :5]}")
print(f"降维后第{i}个样本的坐标: {X_tsne[i]}")

关键点说明:

  1. 顺序对应X_tsne[0]对应X[0]X_tsne[1]对应X[1],依此类推。这个对应关系是严格保持的。
  2. 标签同步:如果你有标签数据y,降维后可视化时,y[i]的标签就对应X_tsne[i]这个点。
  3. fit_transform vs fit + transformfit_transform()在单次降维时使用。如果你需要对新数据(训练集外的数据)降维,理论上应该用fit()拟合训练集,再用transform()转换新数据,但注意:TSNE通常没有transform方法,因为它不是线性变换,且设计初衷就是可视化整个数据集。

一个完整的可视化示例,展示如何保持对应关系:

import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.manifold import TSNE

# 加载手写数字数据集
digits = load_digits()
X = digits.data  # 特征 (1797, 64)
y = digits.target  # 标签 (1797,)

# TSNE降维
tsne = TSNE(n_components=2, random_state=42)
X_tsne = tsne.fit_transform(X)

# 可视化:用颜色表示原始标签
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, 
                     cmap='tab10', alpha=0.6, s=20)
plt.colorbar(scatter, label='Digit Label')
plt.title('TSNE Visualization of Digits Dataset')
plt.xlabel('TSNE Component 1')
plt.ylabel('TSNE Component 2')

# 验证对应关系:标注几个点
for idx in [0, 100, 500, 1000]:  # 选几个样本
    plt.annotate(f'X[{idx}]->y={y[idx]}', 
                xy=(X_tsne[idx, 0], X_tsne[idx, 1]),
                xytext=(5, 5), textcoords='offset points',
                fontsize=8, alpha=0.7)
plt.show()

常见问题:

  • 数据洗牌:如果你在降维前对数据进行了洗牌(比如用sklearn.utils.shuffle),必须同时对标签进行相同的洗牌,否则对应关系会错乱。
  • 数据分割:如果先分割数据再分别降维,对应关系会乱,应该先降维再分割,或者确保用相同的随机种子。

总结:索引即对应关系,保持顺序即可。

一个向量一个向量降就可以了吧

QAQ,这么残忍的么

现在的想法是一方面用 doc2vec 做句向量,一方面把 360w 个循环进行均值,取最后 3w 个左右结果,然后再做,目前的话切片之后跑个万条是没问题的

200 维这么整,是 w2v 的结果?

没用过 tsne,输入可以是稀疏矩阵或者生成器吗

试试 pca 或者用 SPSS 做主成分分析…

换个大内存的机器跑吧

好哒,这就去这就去

是 word2vec,这个是抓取的部分社交网站用户的发言,之后做的向量化,输入是 np.array

跑不动了…我选择向量加一加,数量级降下来再跑,应该还是对数据集有代表性的吧?

应该是内存扛不住了。
不过就算能跑出来,360w 也没法看吧,可以采样一部分比较重要的词做降维,比如可以按 embedding 向量的范数排序,选最大的几千个先看看。
另外如果要用 python 来搞,https://github.com/DmitryUlyanov/Multicore-TSNE 比 sklearn 的效率会高很多。

好哒!谢谢大佬!很有用!

滑窗 归一 然后有中间步骤的话 记得每部 保存磁盘序列化对象
成本最小的是加内存 妈的 昨天晚上刚跑了 8600w+

我是每个 100w 然后结果再下一步 呵呵 然后多进程

TSNE 的文档,建议使用 PCA 或 TruncatedSVD 降维

It is highly recommended to use another dimensionality reduction method (e.g. PCA for dense data or TruncatedSVD for sparse data) to reduce the number of dimensions to a reasonable amount (e.g. 50) if the number of features is very high.

估计 sklearn 吃不消的

回到顶部