You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将预训练模型的Tensor嵌入降维至三维坐标?TSNE报错解决

问题解决与方案梳理

先解决报错:perplexity must be less than n_samples

这个错误逻辑很直接:你设置的perplexity=50必须小于样本总数,但你的代码里只输入了1个词,样本数远小于50,必然报错。

  • 如果你要做词对比可视化,至少要准备多个待对比的词(比如10个以上),再把perplexity设成样本数的1/5到1/10左右(比如20个样本就设perplexity=3-4);单个样本没法做t-SNE,它的作用是展示多个样本的空间分布。

你的代码里还有几个明显错误

  1. 变量名混乱:你定义了result = auto_model(**batch_dict),但后面调用了outputs.last_hidden_state,应该改成result.last_hidden_state;
  2. text_list未定义:需要把所有待对比的词放进这个列表,比如text_list = ["Slartibartfast", "Ford Prefect", "Arthur Dent"];
  3. 嵌入提取逻辑错误:embeddings = outputs.last_hidden_state[:, 0][:768]完全不对,[:,0]是取<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]> token的嵌入,形状是[样本数, 768],后面加[:768]会错误截断样本维度,正确写法是embeddings = result.last_hidden_state[:, 0],得到每个样本的<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]> token嵌入。

修正后的基础代码示例:

from sklearn.manifold import TSNE
from transformers import AutoModel, AutoTokenizer
import torch
import matplotlib.pyplot as plt

# 待对比的词列表(至少多个)
text_list = ["Slartibartfast", "Ford Prefect", "Arthur Dent", "Zaphod Beeblebrox", "Marvin"]

# 模型初始化
model_name = 'Alibaba-NLP/gte-multilingual-base'
tokenizer = AutoTokenizer.from_pretrained(model_name)
auto_model = AutoModel.from_pretrained(model_name, trust_remote_code=True)

# 生成嵌入(加torch.no_grad()节省显存)
batch_dict = tokenizer(text_list, padding=True, truncation=True, return_tensors='pt')
with torch.no_grad():
    result = auto_model(**batch_dict)
# 取<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]> token嵌入作为词的表征
embeddings = result.last_hidden_state[:, 0]

# t-SNE降维:perplexity设为小于样本数,这里5个样本设为2
tsne = TSNE(n_components=3, learning_rate='auto', init='random', perplexity=2)
embeddings_3d = tsne.fit_transform(embeddings.detach().numpy())

# 3D可视化
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
for i, word in enumerate(text_list):
    ax.scatter(embeddings_3d[i,0], embeddings_3d[i,1], embeddings_3d[i,2], label=word)
ax.legend()
plt.show()

关于Skip Gram与可行性的疑问

  1. 不需要专门生成Skip Gram:Skip Gram是Word2Vec的训练架构,你用的GTE属于BERT类预训练模型,本身就能输出高质量的词/句子嵌入,直接用这些嵌入做t-SNE降维可视化,就能实现“在平面/三维空间找相似词”的目的——相似的词会在空间中聚集,效果逻辑和Skip Gram可视化一致。
  2. 用预训练模型做这件事完全可行:只要正确提取词嵌入(如果是多字词,BERT会拆分成子词,你可以取子词嵌入的均值/最大值来代表整个词的嵌入,而非只用<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]> token),再通过t-SNE/UMAP等降维算法转到2/3维,就能直观看到词的相似性,避免两两计算相似度的指数级复杂度。

多字词嵌入提取示例:

def get_word_embedding(text, tokenizer, model):
    inputs = tokenizer(text, return_tensors='pt', add_special_tokens=True)
    with torch.no_grad():
        outputs = model(**inputs)
    # 去掉<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]>和</s> token,取子词嵌入的均值
    subword_embeddings = outputs.last_hidden_state[:, 1:-1, :]
    word_embedding = subword_embeddings.mean(dim=1)
    return word_embedding

# 批量处理生成所有词的嵌入
embeddings = torch.cat([get_word_embedding(word, tokenizer, auto_model) for word in text_list], dim=0)

内容的提问来源于stack exchange,提问作者linkey apiacess

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:13:14