大家好,我是小寒。
今天给大家分享自然语言处理中常用的词嵌入(Word embedding)技术
Word embedding 是自然语言处理(NLP)中的一种技术,用于将词汇映射到连续向量空间,以便能够更好地处理和分析文本数据。
这些向量(嵌入)能够捕捉到词汇之间的语义关系和上下文信息。
图片
常用的 word embedding 技术
1.One-Hot Encoding
One-Hot Encoding 是最简单的词嵌入方法,将每个词表示为一个词汇表大小的向量,在该向量中,只有一个位置为1,其余位置为0。
优点
- 简单易实现。
- 没有任何假设或学习过程。
缺点
- 维度非常高,词汇表越大,向量维度越高。
- 不能捕捉词汇之间的语义关系。
- 稀疏表示,效率低下。
from sklearn.preprocessing import OneHotEncoder
import numpy as np
# Sample data
corpus = ['dog', 'cat', 'dog', 'fish']
# Reshape data to fit the model
corpus = np.array(corpus).reshape(-1, 1)
# One-hot encode the data
onehot_encoder = OneHotEncoder(sparse=False)
onehot_encoded = onehot_encoder.fit_transform(corpus)
print(onehot_encoded)
#output
[[0. 1. 0.]
[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
2.Bag of Words (BoW)
词袋法 (BOW) 是自然语言处理 (NLP) 中的一种简单技术,用于将文本文档表示为数字向量。
其理念是将每个文档视为一个单词袋或单词集合,然后计算文档中每个单词的频率。
它不考虑单词的顺序,但提供了一种将文本转换为向量的直接方法。
优点
- 简单易实现。
- 对小规模文本有效。
缺点
- 词汇表大的情况下,向量维度高。
- 不能捕捉词汇的顺序和语义关系。
- 对常用词和不常用词一视同仁,不能区分重要词汇。
from sklearn.feature_extraction.text import CountVectorizer
# Sample data
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
# Initialize the CountVectorizer
vectorizer = CountVectorizer()
# Fit and transform the corpus
X = vectorizer.fit_transform(corpus)
print(X.toarray())
print(vectorizer.get_feature_names_out())
#output of the above code
[[0 1 1 1 0 0 1 0 1]
[0 2 0 1 0 1 1 0 1]
[1 0 0 1 1 0 1 1 1]
[0 1 1 1 0 0 1 0 1]]
['and' 'document' 'first' 'is' 'one' 'second' 'the' 'third' 'this']
3.TF-IDF
TF-IDF 是对 BoW 的改进,它通过降低常用词的权重同时增加稀有词的权重来考虑单词的重要性。
TF-IDF 背后的理念是通过考虑两个因素来计算文档中单词的重要性:
- 词频 (TF):这衡量了某个词在文档中出现的频率。频率越高,该词对该文档就越重要。
- 逆文档频率 (IDF):它是衡量某个词在语料库中所有文档的重要性的指标。它基于这样的直觉:出现在许多文档中的单词比出现在较少文档中的单词信息量更少。
公式:
- TF:词频,表示词 t 在文档 d 中出现的次数。词在文档中出现的次数文档中的总词数
- IDF:逆文档频率,衡量词在整个语料库中的稀有程度。文档总数包含词的文档数
- TF-IDF:TF 和 IDF 的乘积。
优点
- 强调重要词汇,减弱常见词的影响。
- 适用于信息检索和文本挖掘。
缺点
- 仍然是稀疏向量,维度高。
- 不能捕捉词汇的顺序和语义关系。
from sklearn.feature_extraction.text import TfidfVectorizer
# Sample data
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
# Initialize the TfidfVectorizer
vectorizer = TfidfVectorizer()
# Fit and transform the corpus
X = vectorizer.fit_transform(corpus)
print(X.toarray())
print(vectorizer.get_feature_names_out())
#output
[[0. 0.46979139 0.58028582 0.38408524 0. 0.
0.38408524 0. 0.38408524]
[0. 0.6876236 0. 0.28108867 0. 0.53864762
0.28108867 0. 0.28108867]
[0.51184851 0. 0. 0.26710379 0.51184851 0.
0.26710379 0.51184851 0.26710379]
[0. 0.46979139 0.58028582 0.38408524 0. 0.
0.38408524 0. 0.38408524]]
['and' 'document' 'first' 'is' 'one' 'second' 'the' 'third' 'this']
4.Word2Vec
Word2Vec 是一种基于神经网络的模型,可生成单词的密集向量表示。
Word2Vec 的基本思想是训练神经网络以预测给定目标词的上下文词,然后使用生成的向量表示来捕获单词的语义。
它使用两种主要方法捕获单词之间的语义关系:连续词袋 (CBOW) 和 Skip-gram。
- 连续词袋模型(CBOW):根据周围的上下文词预测目标词。
- Skip-Gram:根据目标词预测周围的上下文词。
图片
优点
- 能捕捉词汇的语义关系。
- 生成的词向量密集且维度较低。
- 在大规模语料库上训练效果显著。
缺点
- 需要大量语料进行训练。
- 对计算资源要求较高。
from gensim.models import Word2Vec
# Sample data
sentences = [
['this', 'is', 'the', 'first', 'document'],
['this', 'document', 'is', 'the', 'second', 'document'],
['and', 'this', 'is', 'the', 'third', 'one'],
['is', 'this', 'the', 'first', 'document']
]
# Initialize the Word2Vec model
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, workers=4)
# Train the model
model.train(sentences, total_examples=len(sentences), epochs=10)
# Get vector for a word
print(model.wv['document'])
5.GloVe
GloVe (Global Vectors for Word Representation) 是由斯坦福大学的研究人员在 2014 年提出的一种词嵌入技术。
它结合了基于统计的全局矩阵分解方法和基于预测的局部上下文窗口方法,旨在通过捕捉词对在大规模语料库中的全局共现信息来学习词向量。
GloVe 通过构建一个词对共现矩阵,并在此基础上进行矩阵分解来学习词向量。共现矩阵的每个元素表示两个词在一定窗口范围内共同出现的次数。GloVe 模型试图找到一个向量表示,使得两个词向量的点积能够很好地近似它们在共现矩阵中的共现概率。
优点
- 能捕捉词汇的语义关系和全局统计信息。
- 生成的词向量密集且维度较低。
- 对大规模语料库有良好表现。
缺点
- 需要大量语料进行训练。
- 对计算资源要求较高。
import gensim.downloader as api
# Download pre-trained GloVe model (choose the size you need - 50, 100, 200, or 300 dimensions)
glove_vectors = api.load("glove-wiki-gigaword-100") # Example: 100-dimensional GloVe
# Get word vectors (embeddings)
word1 = "king"
word2 = "queen"
vector1 = glove_vectors[word1]
vector2 = glove_vectors[word2]
# Compute cosine similarity between the two word vectors
similarity = glove_vectors.similarity(word1, word2)
print(f"Word vectors for '{word1}': {vector1}")
print(f"Word vectors for '{word2}': {vector2}")
print(f"Cosine similarity between '{word1}' and '{word2}': {similarity}")
6.FastText
FastText 是由 Facebook 的 AI 研究团队开发的一种词嵌入技术。
它是 Word2Vec 的扩展,主要特点是将词分解为子词(subword)进行表示,从而能够更好地处理词汇外单词(OOV)和拼写错误的词。
FastText 的核心思想是将每个词分解成一组子词或 n-gram,然后学习这些子词的向量表示。通过子词的组合来表示整个词,能够更好地捕捉词的内部结构信息。
优点
- 处理词汇外单词:由于利用了子词信息,FastText 能够很好地处理词汇表之外的新词。
- 更好的泛化能力:能够捕捉词的内部结构信息,提升词嵌入的泛化能力。
- 高效:在大规模数据上训练速度快,并且生成的词向量质量高。
缺点
- 比 Word2Vec 维度更高
from gensim.models import FastText
# Sample data
sentences = [
['this', 'is', 'the', 'first', 'document'],
['this', 'document', 'is', 'the', 'second', 'document'],
['and', 'this', 'is', 'the', 'third', 'one'],
['is', 'this', 'the', 'first', 'document']
]
# Initialize the FastText model
model = FastText(sentences, vector_size=100, window=5, min_count=1, workers=4)
# Train the model
model.train(sentences, total_examples=len(sentences), epochs=10)
# Get vector for a word
print(model.wv['document'])
7.ELMo
ELMo 是由 AllenNLP 团队开发的一种上下文相关的词嵌入技术。
与传统的词嵌入方法不同,ELMo 生成的词向量依赖于上下文,并且在同一个句子中,同一个词在不同位置的嵌入向量是不同的。
ELMo 使用双向 LSTM 语言模型,从文本中学习词的上下文表示。通过预训练语言模型,然后在特定任务上进行微调,生成动态的上下文相关的词嵌入。
图片
优点
- 上下文相关:能够捕捉词汇在不同上下文中的不同含义。
- 适应性强:在多个 NLP 任务中表现优异,包括命名实体识别(NER)、问答系统等。
import tensorflow as tf
import tensorflow_hub as hub
# Load pre-trained ELMo model from TensorFlow Hub
elmo = hub.load("https://tfhub.dev/google/elmo/3")
# Sample data
sentences = ["This is the first document.", "This document is the second document."]
def elmo_vectors(sentences):
embeddings = elmo.signatures['default'](tf.constant(sentences))['elmo']
return embeddings
# Get ELMo embeddings
elmo_embeddings = elmo_vectors(sentences)
print(elmo_embeddings)
8.BERT
BERT 是一种基于 Transformer 的模型,它通过双向(即从左到右和从右到左)考虑整个句子来生成上下文感知的嵌入。
与 Word2Vec 或 GloVe 等为每个单词生成单一表示的传统词嵌入不同,BERT 根据其上下文为每个单词生成不同的嵌入。
优点
- 上下文双向编码:能够同时捕捉词汇的前后文信息。
- 预训练和微调:通过预训练大规模语言模型,并在特定任务上微调,显著提升模型性能。
- 广泛适用性:在多个 NLP 任务中表现出色,如问答系统、文本分类、命名实体识别等。
from transformers import BertTokenizer, BertModel
import torch
# Load pre-trained BERT model and tokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
# Sample data
sentence = "This is the first document."
# Tokenize input
inputs = tokenizer(sentence, return_tensors='pt')
# Get embeddings
with torch.no_grad():
outputs = model(**inputs)
embeddings = outputs.last_hidden_state
print(embeddings)