NLP基础1_word-embedding
基于github项目:https://github.com/shibing624/nlp-tutorial/tree/main
自然语言处理任务
1) 简单任务
-
拼写检查 Spell Checking
-
关键词检索 Keyword Search
-
同义词查找 Finding Synonyms
-
解析来自网站、文档等的信息
-
机器翻译 Machine Translation
-
语义分析 Semantic Analysis
-
指代消解 Coreference
-
问答系统 Question Answering
文本表示
传统离散表示
在自然语言处理(Natural Language Processing,NLP)领域,文本表示是处理流程的第一步,主要是将文本转换为计算机可以运算的数字。
文本表示方法的技术演进:
符号表示法(Symbolic)
示例:词典编码「自然语言处理」→ {"自":1, "然":2, "语":3, "言":4, "处":5, "理":6}
from sklearn.feature_extraction.text import CountVectorizer
corpus = ["自然语言处理 是 人工智能 的 重要 分支"]
vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
X = vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names_out()) # ['人工智能', '分支', '处理', '自然语言处理', '重要']
词袋模型(Bag-of-Words, BoW)
原理:忽略词序,统计每个词在文档中的出现次数
from sklearn.feature_extraction.text import CountVectorizer
corpus = ["I love NLP.", "NLP is amazing!"]
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)
print(X.toarray()) # 输出:[[1 1 1 0] [0 1 0 1]]
print(vectorizer.vocabulary_) # {'love': 2, 'nlp': 1, 'is': 3, 'amazing': 0}
例子1:
句1:Jane wants to go to Shenzhen 句2:Bob wants to go to Shanghai
使用两个例句来构造词袋: [Jane, wants, to, go, Shenzhen, Bob, Shanghai]
两个例句就可以用以下两个向量表示,对应的下标与映射数组的下标相匹配,其值为该词语出现的次数
句1:[1,1,2,1,1,0,0] 句2:[0,1,2,1,0,1,1]
TF-IDF(词频-逆文档频率)
原理:降低常见词权重,提升重要词权重
TF-IDF = TF(t, d) × IDF(t)
from sklearn.feature_extraction.text import TfidfVectorizer
corpus = ["The cat sat on the mat.", "Dog on mat."]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus)
print(X.toarray()) # 非对称矩阵
优劣对比:
方法 | 优点 | 缺点 |
---|---|---|
BoW | 简单高效,易于实现 | 忽略词序、语义信息,维度灾难 |
TF-IDF | 减少常见词干扰 | 仍无法捕捉语义关系 |
分布式表示(词嵌入)
核心思想:用稠密向量表示词语,捕获语义关联
Word2Vec
原理:通过上下文预测目标词(Skip-Gram)或反之(CBOW)
from gensim.models import Word2Vec
sentences = [["nlp", "is", "cool"], ["deep", "learning", "too"]]
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1)
print(model.wv["nlp"]) # 输出100维向量
向量示例:"king" - "man" + "woman" ≈ "queen"
GloVe(Global Vectors)
原理:基于全局词共现矩阵的加权最小二乘训练
from gensim.scripts.glove2word2vec import glove2word2vec
from gensim.models import KeyedVectors
glove2word2vec("glove.txt", "word2vec_format.txt")
model = KeyedVectors.load_word2vec_format("word2vec_format.txt")
优劣对比:
方法 | 优点 | 缺点 |
---|---|---|
Word2Vec | 高效捕获局部语义 | 未利用全局统计信息 |
GloVe | 结合全局共现统计 | 训练速度较慢 |
上下文感知表示
核心突破:根据上下文动态调整词向量
ELMo(Embeddings from Language Models)
原理:双向LSTM生成上下文相关向量
from allennlp.modules.elmo import Elmo, batch_to_ids
options_file = "https://allennlp.s3.amazonaws.com/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_options.json"
weight_file = "https://allennlp.s3.amazonaws.com/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5"
elmo = Elmo(options_file, weight_file, 1)
character_ids = batch_to_ids(["hello world"])
embeddings = elmo(character_ids)['elmo_representations'][0]
BERT(Bidirectional Encoder Representations)
原理:Transformer编码器 + Masked LM训练
from transformers import BertTokenizer, BertModel
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
inputs = tokenizer("Hello NLP!", return_tensors="pt")
outputs = model(**inputs)
last_hidden_states = outputs.last_hidden_state # [1, seq_len, 768]
向量示例:
同一词在不同上下文的BERT表示:
-
"bank" in "river bank" → [0.2, -0.7, ..., 0.4]
-
"bank" in "bank account" → [0.8, 0.1, ..., -0.3]
方法类型 | 典型代表 | 语义捕获 | 上下文敏感 | 训练成本 | 应用场景 |
---|---|---|---|---|---|
传统离散表示 | BoW, TF-IDF | 弱 | ❌ | 极低 | 简单文本分类 |
静态词嵌入 | Word2Vec | 中等(静态) | ❌ | 中等 | 关键词扩展、推荐 |
上下文动态嵌入 | BERT | 强 | ✔️ | 极高 | 语义理解、问答系统 |