返回列表

词嵌入:让机器理解人类语言的魔法

发布于 ·

词嵌入:让机器理解人类语言的魔法

引言

在自然语言处理(NLP)领域,如何让计算机真正"理解"人类的语言一直是一个核心挑战。传统的文本表示方法如词袋模型(Bag-of-Words)虽然简单有效,但忽略了词语之间的语义关系和上下文信息。近年来,词嵌入(Word Embedding)技术革命性地改变了这一局面,它能够将离散的词汇映射到连续的向量空间中,从而让机器具备了"理解"词语语义的能力。

本文将深入探讨词嵌入的原理、实现方法及其在NLP中的应用,帮助读者全面理解这一关键技术。

什么是词嵌入?

从独热编码说起

传统的文本表示方法是独热编码(One-Hot Encoding),例如词汇表中有10000个词,那么"苹果"这个词会被表示为一个长度为10000的向量,其中只有第500个位置为1,其余为0。这种方法存在两个主要问题:

# 示例:独热编码
vocabulary = ["苹果", "香蕉", "橙子", "葡萄"]
wordtoidx = {"苹果": 0, "香蕉": 1, "橙子": 2, "葡萄": 3}

def onehotencode(word):
vector = [0] * len(vocabulary)
idx = wordtoidx[word]
vector[idx] = 1
return vector

print(onehotencode("苹果")) # [1, 0, 0, 0]

词嵌入的核心思想

词嵌入的核心思想是将每个词映射到一个低维连续向量空间,使得语义相似的词在向量空间中距离更近。这种表示方式能够:

  • 捕捉词语之间的语义关系
  • 支持数学运算(如"国王 - 男人 + 女人 ≈ 女王")
  • 减少维度灾难
  • 提高模型的泛化能力

主流词嵌入算法

1. Word2Vec

Word2Vec是最著名的词嵌入算法之一,由Google团队提出。它包含两种训练方法:

CBOW(Continuous Bag-of-Words)

CBOW通过上下文词预测目标词:

上下文词 -> [?] -> 目标词
from gensim.models import Word2Vec
from gensim.test.utils import commontexts

准备训练数据

sentences = [ ['human', 'interface', 'computer'], ['survey', 'user', 'computer', 'system', 'response', 'time'], ['eps', 'user', 'interface', 'system'] ]

训练Word2Vec模型

model = Word2Vec(sentences, vector
size=100, window=5, mincount=1, workers=4)

获取词向量

vector = model.wv['computer'] # 返回100维向量 print(f"Computer vector shape: {vector.shape}")

查找相似词

similar
words = model.wv.mostsimilar('computer', topn=3) print("Words similar to computer:", similarwords)

Skip-gram

Skip-gram通过目标词预测上下文词:

目标词 -> [?] -> 上下文词

Skip-gram在处理罕见词时表现更好。

2. GloVe(Global Vectors for Word Representation)

GloVe结合了全局统计信息和局部上下文信息,通过构建共现矩阵来学习词向量:

import numpy as np
from collections import defaultdict

class SimpleGloVe:
def init(self, vocabsize, embeddingdim):
self.vocabsize = vocabsize
self.embeddingdim = embeddingdim
self.W = np.random.normal(0, 0.1, (vocabsize, embeddingdim))
self.b = np.zeros((vocabsize,))

def train(self, cooccurrence
matrix, learningrate=0.01, epochs=10):
for epoch in range(epochs):
total
loss = 0
for i in range(self.vocabsize):
for j in range(self.vocab
size):
if cooccurrencematrix[i][j] > 0:
xij = cooccurrence
matrix[i][j]
prediction = np.dot(self.W[i], self.W[j]) + self.b[i] + self.b[j]
loss = xij - prediction

# 更新参数
gradWi = -loss * self.W[j]
gradWj = -loss * self.W[i]
gradbi = -loss
gradbj = -loss

self.W[i] -= learningrate * gradWi
self.W[j] -= learning
rate * gradWj
self.b[i] -= learningrate * gradbi
self.b[j] -= learning
rate * gradbj

totalloss += abs(loss)

print(f"Epoch {epoch+1}, Loss: {total
loss:.4f}")

return self.W

3. FastText

FastText是Facebook提出的改进版本,它不仅考虑词的共现关系,还考虑字符级别的n-gram信息:

from gensim.models import FastText

训练FastText模型

fasttextmodel = FastText(sentences, vectorsize=100, window=5, mincount=1, workers=4, sg=1) # sg=1表示使用Skip-gram

FastText的优势:

- 能够处理未登录词(out-of-vocabulary words)

- 对拼写错误有更好的鲁棒性

- 适合处理形态丰富的语言

获取子词信息

subwords = fasttext
model.wv.getsubwords('unhappiness') print("Subwords for 'unhappiness':", subwords)

词嵌入的应用

1. 语义相似度计算

# 计算词语间的余弦相似度
from sklearn.metrics.pairwise import cosinesimilarity

def calculatesimilarity(model, word1, word2):
vec1 = model.wv[word1].reshape(1, -1)
vec2 = model.wv[word2].reshape(1, -1)
similarity = cosine
similarity(vec1, vec2)[0][0]
return similarity

测试语义相似度

similarity = calculatesimilarity(model, "king", "queen") print(f"Similarity between 'king' and 'queen': {similarity:.4f}")

向量运算演示

king
vector = model.wv['king'] manvector = model.wv['man'] womanvector = model.wv['woman']

result = kingvector - manvector + womanvector
most
similar = model.wv.similarbyvector(result, topn=1)[0]
print(f"'king - man + woman' is most similar to: {mostsimilar[0]}")

2. 情感分析

# 基于词嵌入的情感分类
from sklearn.linearmodel import LogisticRegression
from sklearn.modelselection import traintestsplit
import numpy as np

假设我们有带标签的数据

X
train = [...] # 训练文本的词向量平均 ytrain = [...] # 对应的情感标签

训练分类器

classifier = LogisticRegression() classifier.fit(X
train, ytrain)

预测新文本

def predict
sentiment(text, model, classifier): words = text.lower().split() vectors = [model.wv[word] for word in words if word in model.wv] if len(vectors) == 0: return "neutral" avgvector = np.mean(vectors, axis=0).reshape(1, -1) prediction = classifier.predict(avgvector)[0] return prediction

3. 命名实体识别

# 结合词嵌入的NER系统
def extractentities(text, model):
    words = text.split()
    entities = []
    
    for i, word in enumerate(words):
        # 检查是否为命名实体
        if word in model.wv:
            # 使用上下文信息判断
            contextscore = calculatecontextsimilarity(words, i, model)
            if contextscore > threshold:
                entities.append({
                    'word': word,
                    'position': i,
                    'confidence': contextscore
                })
    
    return entities

实践建议与最佳实践

1. 选择合适的算法

| 场景 | 推荐算法 |
|------|----------|
| 大规模语料库 | Word2Vec |
| 需要处理OOV词 | FastText |
| 精确捕捉全局统计信息 | GloVe |
| 小数据集 | Skip-gram |

2. 超参数调优

```python

网格搜索调优示例


from sklearn.modelselection import ParameterGrid

paramgrid = {
'vectorsize': [50, 100, 200],
'window': [3, 5, 7],
'min
count': [1, 2, 5],
'sg': [0, 1] # 0: CBOW, 1: Skip-gram
}