利用t-SNE可视化Glove向量

本文介绍了GloVe词向量的原理及其与矩阵分解方法的结合,展示了如何使用t-SNE对预训练的GloVe词向量进行二维可视化。通过示例代码,演示了对前100个词向量进行t-SNE降维并绘制图像的过程,结果显示词向量在低维空间中能捕捉到词的语义相似性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、GloVe词向量简介

GloVe:全称Global Vectors for Word Representations。其文献[2]是2014年在EMNLP会议上提出来的。其结合了词向量矩阵分解的思想对原始语料进行预训练,得到了低维、连续、稀疏的表示形式。对预训练后的词向量进行可视化可以发现发现某些词与词之间的联系。
(附:2种常用于估计词向量的方法,
1是基于神经网络的语言模型和word2vec的词向量预训练方法,其本质都是利用文本中词与词在局部上下文中的共现信息作为自监督学习信号。
2.基于矩阵分解的方法,如LSA(Latent Semantic Analysis潜在语义分析)等。其首先对语料进行统计分析,并获得含有全局统计信息的“词-上下文”共现矩阵,然后利用奇异值分解(Singular Value Decomposition,SVD)对该矩阵进行降维,进而得到词的低维表示。然而, 传统的矩阵分解方法得到的词向量不具备良好的几何性质,因此,GloVe词向量就提出来了,其结合了词向量以及矩阵分解的思想,结果较为好)[1]

二、t-SNE简介

t-SNE,全称t-distributed stochastic neighbor embedding。具体过程我不太了解, 但是其可以将高维数据压缩成低维输出。
如输入是(n_sample, n_dimension),输出是(n_sample, 2)。该过程将n_sample个维度为n_dimension的样本压缩成2维。

三、预训练的GloVe词向量

预训练好的词向量放在了官网上,请自行下载:
(网址:https://nlp.stanford.edu/projects/glove/)
在这里插入图片描述
如上图所示,根据不同的语料有不同的预训练模型,如有从Wikipedia、Twitter、以及普通爬取的语料信息。我选择了第一个,即从Wikipedia爬取的数据。
解压改文件后,选择了glove.6B.50d.txt(即从6B个token中提取,有400k的vocab,每个vocab是50维的)。在这里插入图片描述
任意提取该txt文档的5行看一看,发现每行第1个数是token,剩下的50个float类型的数字是该token的50维表示。

were 0.73363 -0.74815 0.45913 -0.56041 0.091855 0.33015 -1.2034 -0.15565 -1.1205 -0.5938 0.23299 -0.46278 -0.34786 -0.47901 0.57621 -0.16053 -0.26457 -0.13732 -0.91878 -0.65339 0.05884 0.61553 1.2607 -0.39821 -0.26056 -1.0127 -0.38517 -0.096929 -0.11701 -0.48536 3.6902 0.30744 0.50713 -0.6537 0.80491 0.23672 0.61769 0.030195 -0.57645 0.60467 -0.63949 -0.11373 0.84984 0.41409 0.083774 -0.28737 -1.4735 -0.20095 -0.17246 -1.0984
not 0.55025 -0.24942 -0.0009386 -0.264 0.5932 0.2795 -0.25666 0.093076 -0.36288 0.090776 0.28409 0.71337 -0.4751 -0.24413 0.88424 0.89109 0.43009 -0.2733 0.11276 -0.81665 -0.41272 0.17754 0.61942 0.10466 0.33327 -2.3125 -0.52371 -0.021898 0.53801 -0.50615 3.8683 0.16642 -0.71981 -0.74728 0.11631 -0.37585 0.5552 0.12675 -0.22642 -0.10175 -0.35455 0.12348 0.16532 0.7042 -0.080231 -0.068406 -0.67626 0.33763 0.050139 0.33465
this 0.53074 0.40117 -0.40785 0.15444 0.47782 0.20754 -0.26951 -0.34023 -0.10879 0.10563 -0.10289 0.10849 -0.49681 -0.25128 0.84025 0.38949 0.32284 -0.22797 -0.44342 -0.31649 -0.12406 -0.2817 0.19467 0.055513 0.56705 -1.7419 -0.91145 0.27036 0.41927 0.020279 4.0405 -0.24943 -0.20416 -0.62762 -0.054783 -0.26883 0.18444 0.18204 -0.23536 -0.16155 -0.27655 0.035506 -0.38211 -0.00075134 -0.24822 0.28164 0.12819 0.28762 0.1444 0.23611
who -0.19461 -0.051277 0.26445 -0.57399 1.0236 0.58923 -1.3399 0.31032 -0.89433 -0.13192 0.21305 0.29171 -0.66079 0.084125 0.76578 -0.42393 0.32445 0.13603 -0.29987 -0.046415 -0.74811 1.2134 0.24988 0.22846 0.23546 -2.6054 0.12491 -0.94028 -0.58308 -0.32325 2.8419 0.33474 -0.33902 -0.23434 0.37735 0.093804 -0.25969 0.68889 0.37689 -0.2186 -0.24244 1.0029 0.18607 0.27486 0.48089 -0.43533 -1.1012 -0.67103 -0.21652 -0.025891
they 0.70835 -0.57361 0.15375 -0.63335 0.46879 -0.066566 -0.86826 0.35967 -0.64786 -0.22525 0.09752 0.27732 -0.35176 -0.25955 0.62368 0.60824 0.34905 -0.27195 -0.27981 -1.0183 -0.1487 0.41932 1.0342 0.17783 0.13569 -1.9999 -0.56163 0.004018 0.60839 -1.0031 3.9546 0.68698 -0.53593 -0.7427 0.18078 0.034527 0.016026 0.12467 -0.084633 -0.10375 -0.47862 -0.22314 0.25487 0.69985 0.32714 -0.15726 -0.6202 -0.23113 -0.31217 -0.3049

4. 编程用t-SNE可视化Glove向量。

scikit-learn库中含有t-SNE的实现,结合官方给出的代码,这里实现了t-SNE可视化Glove词向量。另外由于token太多时图片显示杂乱和算力限制, 这里只显示前100个Glove向量。感兴趣的读者还可以在该代码基础上提取特定的token和不同的token数量进行可视化。

代码如下:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import offsetbox
from sklearn.preprocessing import MinMaxScaler
from sklearn.manifold import TSNE
from time import time
from sklearn.datasets import load_digits

digits = load_digits(n_class=6)

# 1.读取GloVe向量数据库,取6种类。共400,000个token,每个token是50维。
glove_txt = "/home/lwq/20210922/glove.6B.50d.txt"
with open(glove_txt) as f:
    lines = f.readlines()
    lines = lines[:100]
    X = []
    y = []
    for line in lines:
        now = line.split(' ')
        y.append(now[0])
        X.append(now[1:])
    X = np.array(X)
    y = np.array(y)

n_samples, n_features = X.shape


# 2.编写绘画函数,对输入的数据X进行画图。
def plot_embedding(X, title, ax):
    X = MinMaxScaler().fit_transform(X)

    shown_images = np.array([[1.0, 1.0]])  # just something big
    for i in range(X.shape[0]):
        # plot every digit on the embedding
        ax.text(
            X[i, 0],
            X[i, 1],
            str(y[i]),
            # color=plt.cm.Dark2(y[i]),
            fontdict={"weight": "bold", "size": 9},
        )
        '''
        # show an annotation box for a group of digits
        dist = np.sum((X[i] - shown_images) ** 2, 1)
        if np.min(dist) < 4e-3:
            # don't show points that are too close
            continue
        shown_images = np.concatenate([shown_images, [X[i]]], axis=0)
        imagebox = offsetbox.AnnotationBbox(
            offsetbox.OffsetImage(digits.images[i], cmap=plt.cm.gray_r), X[i]
        )
        ax.add_artist(imagebox)
        '''
    ax.set_title(title)
    ax.axis("off")


# 3.选择要用那种方式对原始数据编码(Embedding),这里选择TSNE。
#  n_components = 2表示输出为2维,learning_rate默认是200.0,
embeddings = {
    "t-SNE embeedding": TSNE(
        n_components=2, init='pca', learning_rate=200.0, random_state=0
    ),
}


# 4.根据字典里(这里只有TSNE)的编码方式,生成压缩后的编码矩阵
# 即把每个样本生成了2维的表示。维度由原来的50位变成了2位。
# Input: (n_sample, n_dimension)
# Output: (n_sample, 2)

projections, timing = {}, {}
for name, transformer in embeddings.items():
    # 原作者的dict里有多种比较方法,我只用了t-SNE,需要的可以查询原链接:https://scikit-learn.org/stable/auto_examples/manifold/plot_lle_digits.html#manifold-learning-on-handwritten-digits-locally-linear-embedding-isomap
    if name.startswith("Linear Discriminant Analysis"):
        data = X.copy()
        data.flat[:: X.shape[1] + 1] += 0.01  # Make X invertible
    else:
        data = X

    print(f"Computing {name}...")
    start_time = time()
    print(data.shape, type(data.shape))
    projections[name] = transformer.fit_transform(data, y)
    timing[name] = time() - start_time



# 6.把编码矩阵输出到二维图像中来。
fig, ax = plt.subplots()
title = f"{name} (time {timing[name]:.3f}s)"
plot_embedding(projections[name], title, ax)
plt.show()

结果如下:
在这里插入图片描述

上图 :利用t-SNE对前100个GloVe词向量可视化结果

从图中我们可以发现,最上面的标点符号聚到了一起,表明他们是相似的。his、her、he、who分到了一起。year和years分到了一起,表现了一些语义的相似性。这在不同的corpus上、不同维度上可能显示的结果是不一样的。

根据结果这表明Glove词向量是具有一定的相关性的。但是GloVe词向量是静态词向量,不能解决NLP任务中的“一词多义”问题。因此,可以考虑一些动态的词向量表示,如Elmo模型、以及现在特别流行的GPT、BERT等预训练模型。


参考文献

1.《自然语言处理:基于预训练模型的方法》车万翔等著,2021年。
2.Jeffrey Pennington, Richard Socher, and Christopher D. Manning. 2014. GloVe: Global Vectors for Word Representation.
3.https://scikit-learn.org/stable/auto_examples/manifold/plot_lle_digits.html#manifold-learning-on-handwritten-digits-locally-linear-embedding-isomap

### t-SNE 的定义与作用 t-SNE(t-distributed Stochastic Neighbor Embedding)是一种用于降维和可视化的非线性技术,特别适用于高维数据的低维表示。其核心目标是将高维空间中的相似性关系转换为低维空间中的概率分布,并通过优化这些概率分布之间的差异来生成可视化结果[^2]。 t-SNE 的主要作用在于揭示高维数据中的局部结构,能够有效捕捉数据点之间的近邻关系,因此在数据可视化领域具有广泛的应用价值。它通过减少维度的同时尽量保持原始数据中点对点的相似性,使得复杂的数据集可以在二维或三维空间中以直观的形式展现出来[^1]。 --- ### t-SNE 算法的原理 #### 1. 高维空间中的相似性 在高维空间中,t-SNE 使用高斯分布计算每一对数据点之间的条件概率 \( p_{j|i} \),表示点 \( j \) 在点 \( i \) 的条件下的相似性。该概率值越大,说明两点越接近。对于所有点的联合概率 \( p_{ij} \),则通过对称化处理得到: \[ p_{ij} = \frac{p_{j|i} + p_{i|j}}{2N} \] 其中 \( N \) 是数据点的数量[^1]。 #### 2. 低维空间中的相似性 在低维空间中,t-SNE 使用学生t分布(t-distribution)来定义点对之间的相似性 \( q_{ij} \)。这种分布的特点是长尾特性,可以更好地适应不同密度的数据点分布。通过这种方式,t-SNE 能够在低维空间中保留高维空间中的局部结构。 #### 3. 优化目标 t-SNE 的目标是最小化高维空间的概率分布 \( P \) 和低维空间的概率分布 \( Q \) 之间的KL散度(Kullback-Leibler Divergence)。具体来说,优化问题可以表示为: \[ C = KL(P || Q) = \sum_{i \neq j} p_{ij} \log \frac{p_{ij}}{q_{ij}} \] 为了最小化 \( C \),t-SNE 使用梯度下降方法进行优化。在优化过程中,每个点的位置通过模拟弹簧力的方式调整,以确保低维空间中的点分布尽可能接近高维空间中的相似性关系[^3]。 #### 4. 关键特点 - **局部结构保留**:t-SNE 更加关注数据点的局部相似性,因此适合用于发现数据中的簇结构。 - **非线性映射**:与 PCA 等线性降维方法不同,t-SNE 可以捕捉数据中的非线性关系。 - **计算复杂度较高**:由于需要计算每一对点之间的相似性,t-SNE 的时间复杂度较高,尤其在大规模数据集上表现不佳。 --- ### t-SNE 的应用场景 #### 1. 数据可视化 t-SNE 最常见的应用场景是将高维数据降维到二维或三维空间,以便于观察数据的分布特性。例如,在图像分类任务中,可以通过 t-SNE 将特征向量可视化,从而了解不同类别的分布情况[^2]。 #### 2. 生物信息学 在基因表达数据分析中,t-SNE 被用来揭示细胞类型之间的关系,帮助研究人员理解复杂的生物系统。 #### 3. 自然语言处理 t-SNE 可以用于词向量可视化,展示词语之间的语义关系。例如,Word2Vec 或 GloVe 模型生成的词嵌入可以通过 t-SNE 投影到二维平面上,便于分析词汇的聚类情况。 #### 4. 异常检测 通过 t-SNE 可视化,可以直观地发现数据中的异常点或离群点,这对于质量控制和故障诊断等领域具有重要意义。 --- ### 示例代码 以下是一个使用 Python 实现 t-SNE 的简单示例: ```python import numpy as np import matplotlib.pyplot as plt from sklearn.manifold import TSNE from sklearn.datasets import load_digits # 加载手写数字数据集 data, labels = load_digits(return_X_y=True) # 应用 t-SNE 进行降维 tsne = TSNE(n_components=2, random_state=42) data_2d = tsne.fit_transform(data) # 可视化结果 plt.figure(figsize=(8, 6)) scatter = plt.scatter(data_2d[:, 0], data_2d[:, 1], c=labels, cmap='tab10') plt.colorbar(scatter) plt.title("t-SNE Visualization of Handwritten Digits") plt.xlabel("Dimension 1") plt.ylabel("Dimension 2") plt.show() ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值