当前位置:首页>python>一天一个Python知识点——Day 164:词嵌入技术

一天一个Python知识点——Day 164:词嵌入技术

  • 2026-09-02 20:05:06
一天一个Python知识点——Day 164:词嵌入技术

一、开篇:从“词”到“向量”的跨越

昨天我们用一整天的完成了文本预处理,把脏乱的原始文本变成了干净的词序列:

原始:I absolutely LOVED the movie!!! It was soooo amazing 😍😍😍 #mustwatch处理后:['absolutely', 'love', 'movie', 'amazing', 'mustwatch']

现在的问题是:这些词怎么输入给模型?

神经网络只能处理数字,不能直接处理“movie”、“love”这样的字符串。

最直接的想法:独热编码(One-hot encoding)

movie → [0,0,0,1,0,0,...]  (假设词表大小10000,movie是第4个词)love  → [0,1,0,0,0,0,...]

独热编码的致命问题:

  1. 维度灾难:词表越大,向量越长(10000维)

  2. 语义鸿沟:任何两个词的距离都是相同的,无法表达语义相似性(“猫”和“狗”的距离与“猫”和“汽车”一样远)

解决方案:词嵌入(Word Embedding)

将词映射到低维稠密向量(如300维),使得:

  • 语义相似的词在向量空间中也相近

  • 向量可以捕捉词语间的类比关系(如 国王 - 男人 + 女人 ≈ 王后)

二、词嵌入的核心思想:分布假设

“You shall know a word by the company it keeps.”
—— J.R. Firth (1957)

分布假设:词语的含义由其上下文决定。如果两个词经常出现在相似的上下文中,它们的语义应该相似。

例:

  • “我喝了一杯咖啡”

  • “我喝了一杯茶”

“咖啡”和“茶”都出现在“我喝了一杯”后面,所以它们的向量应该相近。

三、主流词嵌入模型

3.1 Word2Vec (2013) —— 词嵌入的奠基者

Google发布的Word2Vec有两种训练方式:CBOW和Skip-gram。

模型
原理
特点
CBOW
用上下文词预测中心词
训练快,对小数据集好
Skip-gram
用中心词预测上下文词
对罕见词更精准

Skip-gram示意图:

输入:中心词 "coffee" → 预测上下文 ["I", "drank", "a", "cup", "of"]
用代码感受Word2Vec:
from gensim.models import Word2Vecfrom nltk.tokenize import word_tokenizeimport nltknltk.download('punkt')# 准备语料(已经预处理的句子列表)sentences = [    "I love natural language processing".split(),    "Word embeddings are amazing".split(),    "I love coffee and tea".split(),    "Coffee and tea are both beverages".split()]# 训练Word2Vec模型model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, workers=4)# 查看词向量vector = model.wv['coffee']print(f"'coffee'的向量(前10维):{vector[:10]}")# 找相似词similar = model.wv.most_similar('coffee')print("与'coffee'最相似的词:", similar)# 词类比:国王 - 男人 + 女人 ≈ 王后result = model.wv.most_similar(positive=['woman', 'king'], negative=['man'])print("国王 - 男人 + 女人 ≈", result[0][0])

3.2 GloVe (2014) —— 全局共现统计

斯坦福提出的GloVe(Global Vectors)结合了全局矩阵分解和局部上下文窗口的优点。

原理:利用词-词共现矩阵,通过加权最小二乘学习词向量。

特点:

  • 利用全局统计信息

  • 训练速度快(特别是大语料)

from gensim.scripts.glove2word2vec import glove2word2vecfrom gensim.models import KeyedVectors# 将GloVe格式转为Word2Vec格式glove_input_file = 'glove.6B.100d.txt'word2vec_output_file = 'glove.6B.100d.word2vec.txt'glove2word2vec(glove_input_file, word2vec_output_file)# 加载模型model = KeyedVectors.load_word2vec_format(word2vec_output_file, binary=False)# 使用similar = model.most_similar('coffee')print("GloVe中与'coffee'最相似的词:", similar)

3.3 FastText (2016) —— 子词信息的引入

Facebook提出的FastText在Word2Vec的基础上引入了子词信息(subword)。

核心创新:将词拆分成字符级别的n-gram,每个n-gram有自己的向量,词的向量由所有n-gram向量求和得到。

"coffee" → <co, coff, offe, ffee, fee> 等字符n-gram

优势:

  • 可以处理未登录词(OOV),即使没见过的词也能根据子词构造向量

  • 对形态丰富的语言(如德语、俄语)效果好

from gensim.models import FastText# 训练FastTextmodel = FastText(sentences, vector_size=100, window=5, min_count=1, workers=4)# 对于未登录词,仍能得到向量vector_oov = model.wv['never_seen_word']print("未登录词向量(前10维):", vector_oov[:10])# 相似词查找similar = model.wv.most_similar('coffee')print("FastText中与'coffee'最相似的词:", similar)

四、词嵌入的评估

4.1 内在评估

  • 词语相似性:计算人工标注的词对相似度与余弦相似度的相关系数

  • 词语类比:如 巴黎 - 法国 + 意大利 ≈ 罗马

4.2 外在评估

  • 将词向量作为特征,输入下游任务(分类、NER),观察任务性能提升

五、词嵌入的应用场景

场景
说明
语义相似度
计算文档、句子、词之间的相似度
信息检索
用向量相似度召回相关文档
聚类
将相似词聚类,发现话题
特征输入
作为神经网络的第一层输入
词类比推理
解决类比问题

六、实战项目:基于词向量的文本分类

6.1 用预训练词向量做文本分类

import numpy as npfrom sklearn.model_selection import train_test_splitfrom sklearn.linear_model import LogisticRegressionfrom sklearn.metrics import accuracy_scoreimport gensim.downloader as api# 加载预训练的GloVe词向量(第一次运行会下载)print("加载GloVe模型...")glove = api.load("glove-twitter-25")  # 25维,Twitter语料# 示例数据:简单情感句子texts = [    "I love this movie",    "This film is great",    "Terrible waste of time",    "I hate it",    "Absolutely wonderful",    "Worst movie ever",    "Pretty good actually",    "Not bad at all"]labels = [1, 1, 0, 0, 1, 0, 1, 1]  # 1:正面 0:负面def sentence_to_vector(sentence, model):    """将句子中所有词的词向量平均,作为句子向量"""    words = sentence.lower().split()    vectors = [model[word] for word in words if word in model]    if len(vectors) == 0:        return np.zeros(model.vector_size)    return np.mean(vectors, axis=0)# 转换为特征向量X = np.array([sentence_to_vector(s, glove) for s in texts])y = np.array(labels)# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 训练分类器clf = LogisticRegression()clf.fit(X_train, y_train)# 评估y_pred = clf.predict(X_test)print("准确率:", accuracy_score(y_test, y_pred))

6.2 可视化词向量

import matplotlib.pyplot as pltfrom sklearn.decomposition import PCA# 选择一些词words = ['coffee', 'tea', 'milk', 'water', 'juice',          'dog', 'cat', 'fish', 'bird', 'rabbit']# 获取向量vectors = np.array([glove[word] for word in words if word in glove])# PCA降维到2维pca = PCA(n_components=2)vectors_2d = pca.fit_transform(vectors)# 绘制plt.figure(figsize=(8,6))for i, word in enumerate(words):    if word in glove:        plt.scatter(vectors_2d[i,0], vectors_2d[i,1])        plt.annotate(word, (vectors_2d[i,0], vectors_2d[i,1]))plt.title("词向量PCA可视化")plt.show()

七、词向量的局限与发展

7.1 固有局限

  • 静态性:一个词只有一个向量,无法处理多义词(如“bank”)

  • 上下文无关:不考虑句子中的具体语境

  • 训练数据偏差:继承语料中的偏见(如“医生”更接近“男性”)

7.2 下一代:上下文相关的词向量

2018年之后,BERT、ELMo等模型通过深度网络生成了动态词向量——同一个词在不同语境下有不同的向量。

句子1:"He deposited money in the bank."句子2:"He sat on the river bank."
BERT能根据上下文给两个“bank”不同的向量表示。

总结:向量,让词语有了“数学意义”

词嵌入是NLP从符号主义走向连接主义的关键一步。它让词语变成了向量,使得我们可以用数学运算来处理语义——这是深度学习革命的前奏。

今天你学会了:

  • 词嵌入的核心思想:分布假设

  • Word2Vec、GloVe、FastText的原理与使用

  • 用词向量做文本分类

  • 词向量的可视化与局限

最新文章

随机文章