前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >词向量发展历程:技术及实战案例

词向量发展历程:技术及实战案例

作者头像
TechLead
发布2024-04-17 16:27:07
3290
发布2024-04-17 16:27:07
举报
文章被收录于专栏:TechLead

一、词向量简介

词向量(Word Vector)或词嵌入(Word Embedding)是自然语言处理(NLP)中的一项基础技术,它允许我们将自然语言中的词汇表示为实数向量。这些向量通常存在于一个高维空间内,其中每一个维度都可能代表着某种语义属性。通过这种转换,机器学习模型可以捕捉到词语之间复杂的关系,如语义相似性、反义、上下位关系等。

传统的词表示方法,如One-hot编码,虽然简单明了,但存在严重的维度灾难和无法表示词之间语义关系的缺点。例如,对于一个有10000个唯一词的语料库,One-hot编码会产生一个10000维的向量,其中99.99%的元素都是0,这造成了极大的存储和计算资源浪费。更重要的是,这种表示方法无法捕获词与词之间的语义关系,每个词都是孤立的。

相比之下,词向量通过将词表示为稠密的向量(通常几百到几千维),可以有效缓解维度灾难问题,并且因为其连续的特性,相似的词在向量空间中会彼此接近,从而能够捕捉到丰富的语义关系。例如,通过训练得到的词向量,我们可以通过计算向量之间的距离来评估词语之间的相似度。

词向量的生成通常依赖于机器学习模型,这些模型可以是无监督的,如Word2Vec或GloVe,也可以是有监督的,如在特定任务训练中学习到的词嵌入。无监督的模型通过大规模文本语料库学习词语的共现信息,从而捕捉到语义信息。例如,Word2Vec的Skip-gram模型通过预测上下文来学习目标词的向量表示,而GloVe则通过全局词频统计来优化词向量。

词向量技术的应用极为广泛,几乎涵盖了自然语言处理的所有领域,从基础的词性标注、命名实体识别到复杂的机器翻译、情感分析等任务,词向量都发挥着不可或缺的作用。通过预训练的词向量,模型可以更快地收敛,同时提高最终任务的准确率。此外,词向量也被用于构建复杂的神经网络架构,如在深度学习中用作RNN或CNN的输入层,从而进一步提升模型的性能。

二、词向量的技术演进

词向量技术的发展是自然语言处理领域进步的一个缩影。从最初的One-hot编码到现今的上下文敏感型词嵌入,每一步技术的演进都极大地推动了机器对自然语言理解能力的提升。本节将对词向量技术的发展历程进行概述,探讨各个阶段的技术特点和它们之间的联系。

从One-hot到密集向量

One-hot编码

One-hot编码是最早期的词表示方法,每个词被表示为一个很长的向量,向量的长度等于词汇表的大小,该词在词汇表中的位置为1,其余位置为0。这种方法简单直观,但由于向量维度过高且无法表达词之间的关系,很快就显示出了局限性。

密集向量表示

为了克服One-hot编码的缺点,研究者开始探索使用密集向量来表示词汇,即每个词被表示为一个固定长度的实数向量,不再是高维稀疏向量。这些向量通过训练得到,可以捕捉到一定的语义信息,如相似的词会在向量空间中靠近。

Word2Vec: 革命性的起点

Word2Vec由Google在2013年推出,它标志着词向量技术的一个重大突破。Word2Vec有两种训练模型:Skip-gram和CBOW(Continuous Bag of Words)。Skip-gram模型预测给定词汇的上下文,而CBOW模型则是根据上下文预测当前词汇。Word2Vec的成功不仅在于它能有效地捕捉到词语之间的语义和语法关系,更重要的是,它极大地降低了词向量的训练难度和复杂性。

GloVe: 全局词向量

GloVe(Global Vectors for Word Representation)是斯坦福大学在2014年提出的一种词向量生成方法。不同于Word2Vec的局部上下文窗口方法,GloVe通过对整个语料库的共现统计信息进行矩阵分解,旨在直接捕捉词汇间的全局统计信息。这种方法在一定程度上弥补了Word2Vec只能反映局部上下文信息的不足。

面向未来:上下文敏感型词嵌入

ELMo(Embeddings from Language Models)

ELMo是一种动态词向量技术,由Allen NLP在2018年提出。与之前的词向量模型不同,ELMo通过预训练的深度双向语言模型,为每个词生成基于其使用上下文的词向量。这意味着同一个词在不同的语境中会有不同的向量表示,这一特性使ELMo在多项NLP任务中都取得了显著的效果提升。

BERT(Bidirectional Encoder Representations from Transformers)

BERT由Google在2018年提出,是一个基于Transformer的预训练深度学习模型。它的创新之处在于采用双向训练的方法来处理自然语言,能够更好地理解词语在句子中的上下文关系。BERT的出现进一步推动了词向量技术向上下文敏感型词嵌入的演进。

三、One-hot

One-hot编码是自然语言处理中将词语转换为向量的最基础方法之一。在这种编码方式下,每个词被表示为一个很长的向量,这个向量的长度等于词汇表的大小,其中代表该词的位置为1,其余位置为0。尽管One-hot编码因其高维稀疏性和无法表达词之间关系的缺点而逐渐被密集向量表示法取代,但理解One-hot编码对于深入学习词向量技术仍然非常重要。

One-hot编码的实际案例

假设我们有一个非常简单的文本:“apple banana apple grape”。首先,我们需要创建一个词汇表,包括所有不重复的词,然后对每个词进行One-hot编码。

在这个例子中,我们的词汇表是 {"apple", "banana", "grape"},包含3个不同的词,因此每个词将被表示为一个长度为3的向量。

  • "apple" 可能被编码为 [1, 0, 0]
  • "banana" 可能被编码为 [0, 1, 0]
  • "grape" 可能被编码为 [0, 0, 1]

现在,我们将通过Python代码来实现这个One-hot编码过程。

代码语言:javascript
复制
import numpy as np

# 定义文本和词汇表
text = "apple banana apple grape"
words = text.split()
vocab = sorted(set(words))

# 创建词到索引的映射
word_to_index = {word: i for i, word in enumerate(vocab)}

# One-hot编码函数
def one_hot_encode(word, word_to_index):
    # 创建一个全0的向量,长度为词汇表的大小
    one_hot_vector = np.zeros(len(word_to_index))
    # 将对应词的位置设置为1
    one_hot_vector[word_to_index[word]] = 1
    return one_hot_vector

# 对每个词进行One-hot编码
encoded_words = [one_hot_encode(word, word_to_index) for word in words]

print("词汇表:", vocab)
print("编码结果:")
for word, encoded_word in zip(words, encoded_words):
    print(f"{word}: {encoded_word}")

这段代码首先定义了一个简单的文本并从中创建了一个词汇表。然后,通过创建一个词到索引的映射字典,我们能够为每个词生成一个One-hot向量。最后,我们打印出了每个词及其对应的One-hot编码结果。

通过这个例子,我们可以看到One-hot编码是如何工作的。虽然这种方法直观且易于实现,但当词汇表很大时,它会产生非常高维且大多数元素为0的向量,从而导致计算资源的浪费。此外,One-hot编码无法表达词之间的任何语义关系,这是其在自然语言处理任务中的一个重大局限性。

四、Word2Vec

密集向量表示法,与One-hot编码形成对比,为每个词提供了一个更紧凑、含义丰富的表示。这种表示法不再是高维稀疏的,而是在低维空间中为每个词分配一个密集的向量,这些向量可以通过训练学习得到,以捕捉词与词之间的细微关系。本节通过一个简化的实例和Python代码演示,来说明如何使用预训练的Word2Vec模型进行词的密集向量表示。

密集向量表示的实际案例

假设我们有一个句子 "I love apples",我们希望获得句子中每个词的密集向量表示。为了简化示例,我们将使用Google的预训练Word2Vec模型。这个模型是在大规模文本数据上训练的,能够为数百万个英语单词提供预先学习好的密集向量表示。

首先,你需要安装gensim库,这是一个专门用于主题建模和文本挖掘的Python库,支持加载Word2Vec等模型。

代码语言:javascript
复制
pip install gensim

接下来,我们将用Python代码加载预训练的Word2Vec模型,并获取我们示例句子中词语的向量表示。

代码语言:javascript
复制
from gensim.models import KeyedVectors

# 加载预训练的Word2Vec模型
# Google的预训练模型较大,加载可能需要一些时间
# 请确保你有足够的内存空间
model = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)

# 示例句子
sentence = "I love apples"

# 分词
words = sentence.lower().split()

# 获取每个词的密集向量表示
word_vectors = [model[word] for word in words if word in model]

for word, vector in zip(words, word_vectors):
    print(f"Word: {word}\nVector: {vector[:10]}... \n")

在这段代码中,我们首先加载了Google的预训练Word2Vec模型,该模型包含300维的词向量。然后,我们将示例句子中的每个词转换为小写,并分割为单词列表。对于句子中的每个词,我们通过模型获取其300维的密集向量表示。由于向量较长,这里只展示了每个向量的前10个元素。

请注意,由于预训练模型的大小,这里的代码仅作为示例。在实际操作中,你需要下载Google的预训练Word2Vec模型,并将其路径替换到代码中相应的位置。

通过这个示例,我们可以看到,不同于One-hot编码的高维稀疏向量,密集向量表示法为每个词提供了一个紧凑且富有语义的向量。这些向量不仅可以捕捉词之间的语义和语法关系,还可以在许多NLP任务中被有效地使用,如文本分类、情感分析等。

五、GloVe举例

GloVe(Global Vectors for Word Representation)是一种基于全局词频统计的词向量生成方法,由斯坦福大学的研究者开发。与Word2Vec不同,GloVe模型通过对整个语料库的共现词频矩阵进行分解,试图捕获词与词之间的全局关系。这种方法使得生成的词向量能够有效反映词之间的语义和语法关联。

GloVe的实际案例

考虑到使用预训练的GloVe模型可以直接为我们提供密集的词向量,我们将通过一个简单的例子来展示如何使用这些预训练的向量。为了本示例,假设我们想要获取句子 "The quick brown fox jumps over the lazy dog" 中每个词的向量表示。

首先,你需要下载预训练的GloVe模型。GloVe提供了多个版本的预训练词向量,这里我们使用其中一个较小的版本,如glove.6B.50d.txt,其中每个词被表示为一个50维的向量。

接下来,我们将用Python代码加载预训练的GloVe模型,并获取我们示例句子中词语的向量表示。

代码语言:javascript
复制
import numpy as np

def load_glove_model(glove_file):
    """加载GloVe模型"""
    with open(glove_file, 'r', encoding='utf-8') as f:
        model = {}
        for line in f:
            split_line = line.split()
            word = split_line[0]
            embedding = np.array([float(val) for val in split_line[1:]])
            model[word] = embedding
        return model

# 加载GloVe模型
glove_path = 'glove.6B.50d.txt' # 确保这里的路径与你的GloVe文件路径相匹配
glove_model = load_glove_model(glove_path)

# 示例句子
sentence = "The quick brown fox jumps over the lazy dog"

# 分词并转换为小写
words = sentence.lower().split()

# 获取每个词的向量表示
word_vectors = [glove_model[word] for word in words if word in glove_model]

for word, vector in zip(words, word_vectors):
    print(f"Word: {word}\nVector: {vector[:10]}... \n")

这段代码首先定义了一个load_glove_model函数来读取并加载GloVe模型文件。然后,我们加载了一个预训练的GloVe模型,并对一个示例句子中的每个词获取其向量表示。最后,我们打印出了每个词及其对应的向量的前10个元素,以便查看。

六、ELMo举例

ELMo(Embeddings from Language Models)是一种深度上下文化的词表示方法,由Allen Institute for AI在2018年提出。与以往的词向量模型不同,ELMo考虑了词在特定上下文中的含义,为同一词在不同语境下生成不同的向量表示。这种动态特性使得ELMo在多项自然语言处理任务中展现出了卓越的性能。

ELMo的实际案例

为了简化示例,我们将使用AllenNLP库来加载预训练的ELMo模型,并获取句子 "I have a green pen" 中"green"这个词的向量表示,以观察ELMo如何处理上下文信息。

首先,你需要安装allennlp库,这是一个开源NLP研究库,支持加载ELMo等模型。

代码语言:javascript
复制
pip install allennlp==2.1.0 allennlp-models==2.1.0

接下来,我们将用Python代码加载预训练的ELMo模型,并获取我们示例句子中"green"这个词的向量表示。

代码语言:javascript
复制
from allennlp.modules.elmo import Elmo, batch_to_ids

# 定义ELMo的配置和权重文件位置
options_file = "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_options.json"
weight_file = "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5"

# 初始化ELMo
elmo = Elmo(options_file, weight_file, 1, dropout=0)

# 示例句子
sentences = [["I", "have", "a", "green", "pen"]]

# 将句子转换为字符id
character_ids = batch_to_ids(sentences)

# 使用ELMo获取词向量
embeddings = elmo(character_ids)

# 获取"green"的向量表示
green_vector = embeddings['elmo_representations'][0][0][3].detach().numpy()

print(f"Vector for 'green':\n{green_vector}")

在这段代码中,我们首先加载了预训练的ELMo模型,并准备了一个示例句子。通过使用batch_to_ids函数,我们将句子转换为ELMo能够处理的字符ID格式。然后,我们使用ELMo模型获取了句子中每个词的向量表示,并提取了"green"这个词的向量。

七、BERT举例

BERT(Bidirectional Encoder Representations from Transformers)是Google在2018年提出的一种预训练深度学习模型,它在自然语言处理领域取得了革命性的进步。BERT的核心特点是利用Transformer的双向编码器表示来理解上下文,能够同时考虑到词语左右两边的上下文信息。这种全面的上下文理解能力使得BERT在多项NLP任务上都表现出色。

BERT的实际案例

为了简化示例,我们将使用Hugging Face的transformers库来加载预训练的BERT模型,并获取句子 "The capital of France is Paris" 中"capital"这个词的向量表示。

首先,你需要安装transformers库。

代码语言:javascript
复制
pip install transformers

接下来,我们将用Python代码加载预训练的BERT模型,并获取我们示例句子中"capital"这个词的向量表示。

代码语言:javascript
复制
from transformers import BertTokenizer, BertModel
import torch

# 初始化分词器和模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

# 示例句子
text = "The capital of France is Paris"

# 对文本进行分词处理
inputs = tokenizer(text, return_tensors="pt")

# 获取词嵌入
with torch.no_grad():
    outputs = model(**inputs)

# 获取最后一层的隐藏状态,它是包含句子中每个token表示的张量
last_hidden_states = outputs.last_hidden_state

# 假设我们要获取 "capital" 的向量表示
# 由于BERT是基于subword的tokenizer,我们需要先找到 "capital" 的token位置
capital_ids = tokenizer.encode("capital", add_special_tokens=False)
capital_index = inputs['input_ids'][0].tolist().index(capital_ids[0])

# 获取 "capital" 的向量表示
capital_vector = last_hidden_states[0][capital_index]

print(f"Vector for 'capital':\n{capital_vector}")

在这段代码中,我们首先加载了预训练的BERT模型及其对应的分词器。通过对示例句子进行分词处理,我们获得了模型需要的输入格式。然后,我们计算了句子中每个token的向量表示,并提取了"capital"这个词的向量。由于BERT使用subword分词机制,我们需要特别注意如何精确地定位到我们关心词语的表示。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 TechLead 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、词向量简介
  • 二、词向量的技术演进
    • 从One-hot到密集向量
      • One-hot编码
      • 密集向量表示
    • Word2Vec: 革命性的起点
      • GloVe: 全局词向量
        • 面向未来:上下文敏感型词嵌入
          • ELMo(Embeddings from Language Models)
          • BERT(Bidirectional Encoder Representations from Transformers)
      • 三、One-hot
        • One-hot编码的实际案例
        • 四、Word2Vec
          • 密集向量表示的实际案例
          • 五、GloVe举例
            • GloVe的实际案例
            • 六、ELMo举例
              • ELMo的实际案例
              • 七、BERT举例
                • BERT的实际案例
                相关产品与服务
                NLP 服务
                NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档